package net.takela.common.webflux.security.handler;

import net.takela.common.webflux.security.model.AuthUser;
import net.takela.common.webflux.security.service.AuthTokenManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * @author zhangyinghui
 * create at 2023/6/29
 */
public class JwtSecurityContextRepository implements ServerSecurityContextRepository {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final AuthTokenManager authTokenManager;
    /**
     * 
     */
    public JwtSecurityContextRepository(AuthTokenManager authTokenManager) {
        this.authTokenManager = authTokenManager;
    }

    
    /**
     * 
     */
    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        return Mono.empty();
    }

    
    /**
     * 
     */
    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        logger.info("加载token:JwtSecurityContextRepository");
        AuthUser user = authTokenManager.parseUserInfoFromRequest(exchange.getRequest(), AuthUser.class);
        if (user != null) {
            //TODO://加载权限
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("0");
            user.setAuthorities(auths);
//                String jti = claims.getId();
//                UserAuthToken userAuthToken = userAuthTokenService.getTokenByClientId(jti);
//                if (userAuthToken == null){
//                    throw new BadCredentialsException("Token is invalid");
//                }
//                Long uid = Long.parseLong( claims.getSubject());
//                //配置权限
////                AuthUser user = new AuthUser("baboy", new BCryptPasswordEncoder().encode("123"), auths);
//                AuthUser user = new AuthUser("baboy", null, auths);
//                user.setUid(uid);
            Authentication authentication = new UsernamePasswordAuthenticationToken(
                    user, null, user.getAuthorities());

            SecurityContext emptyContext = SecurityContextHolder.createEmptyContext();
            emptyContext.setAuthentication(authentication);
            return Mono.just(emptyContext);

//        String path = exchange.getRequest().getPath().toString();
//        // 过滤路径
//        if ("/login".equals(path)){
//            return Mono.empty();
//        }
//        String token = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
//        if (StringUtils.isNotBlank(token)){
//            // token能正常解析，表示token有效并对应数据库已知用户
//            String subject = JwtTokenUtils.parseToken(token);
//            Authentication newAuthentication = new UsernamePasswordAuthenticationToken(subject, subject);
//            return new ReactiveAuthenticationManager(){
//                @Override
//                public Mono<Authentication> authenticate(Authentication authentication) {
//                    // 如果对token有足够的安全认可，可以采用无状态凭证策略，将username和authorities放置在token串中解析获取，此处就可以不用查询数据库验证
//                    Mono<UserDetails> userDetails = userService.findByUsername(authentication.getPrincipal().toString());
//                    UserDetails user = userDetails.block();
//                    if (user == null){
//                        throw new DisabledException("账户不可用");
//                    }
//                    Authentication auth = new UsernamePasswordAuthenticationToken(user.getUsername(), null, user.getAuthorities());
//                    return Mono.just(auth);
//                }
//            }.authenticate(newAuthentication).map(SecurityContextImpl::new);
//        }else {
//            return Mono.empty();
//        }
        }
        return Mono.empty();
    }
}
